﻿using ManagementSystem.App_LocalResources;
using ManagementSystem.Areas.BMS.Models.Role;
using ManagementSystem.Filter;
using ManagementSystem.Models;
using MS.Entities;
using MS.Enums.Common;
using MS.Identity;
using MS.Logic;
using MS.Utility.Common;
using MS.Utility.Config;
using MS.Utility.EF;
using MS.Utility.EnumHelper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
using System.Web.Mvc;

namespace ManagementSystem.Areas.BMS.Controllers
{
    [LoginFilter(Platform.BMS)]
    public class RoleController : Controller
    {
        // GET: BMS/Role
        public ActionResult Index()
        {
            return View();
        }
        public ActionResult RoleFunction()
        {
            int id = Convert.ToInt32(RouteData.Values["id"]);
            MS_Base_RoleLogic roleLogic = MS_Base_RoleLogic.GetInstance();
            var role = roleLogic.GetItemByQuery(x => x.Id == id && x.Status >= (int)RoleStatus.Normal);
            if (role == null)
            {
                HttpContext.Response.Redirect("/BMS/Error/404");
            }
            return View(role);

        }
        public ActionResult UserRole()
        {
            int id = Convert.ToInt32(RouteData.Values["id"]);
            MS_Base_RoleLogic roleLogic = MS_Base_RoleLogic.GetInstance();
            var role = roleLogic.GetItemByQuery(x => x.Id == id && x.Status >= (int)RoleStatus.Normal);
            if (role == null)
            {
                HttpContext.Response.Redirect("/BMS/Error/404");
            }
            return View(role);
        }

        #region 获取角色用户列表
        /// <summary>
        /// 获取角色用户列表
        /// </summary>
        /// <param name="param"></param>
        /// <param name="roleId"></param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult GetUserRoleList(BootstrapTablePageParamModel param, int roleId)
        {
            PageListModel pageListModel = new PageListModel();
            MS_Base_UserRoleLogic userRoleLogic = MS_Base_UserRoleLogic.GetInstance();
            MS_UserCenter_UserAccountLogic userAccountLogic = MS_UserCenter_UserAccountLogic.GetInstance();
            MS_UserCenter_UserAttrLogic userAttrLogic = MS_UserCenter_UserAttrLogic.GetInstance();

            int totalRecords = 0;
            List<MS_Base_UserRole> userRoleList = userRoleLogic.GetPagedList(param.offset, param.limit, x => x.RoleId == roleId && x.Status == (int)Status.Normal, param.sort, param.sortOrder == "desc", out totalRecords);
            List<long> uids = (from o in userRoleList select o.Uid).ToList();

            long[] uidArr = userRoleList.Select(x => x.UpdateUid).ToArray();
            List<MS_UserCenter_UserAttr> userList = userAttrLogic.GetListByQuery((x => uidArr.Contains(x.Uid)), string.Empty, false);

            List<MS_UserCenter_UserAccount> userAccountList = userAccountLogic.GetListByQuery(x => uids.Contains(x.Uid), null, false);
            List<MS_UserCenter_UserAttr> userAttrList = userAttrLogic.GetListByQuery(x => uids.Contains(x.Uid), null, false);
            var tableJson = from userRole in userRoleList
                            join userAccount in userAccountList on userRole.Uid equals userAccount.Uid //内连接 等效于inner join
                            join userAttr in userAttrList on userRole.Uid equals userAttr.Uid into u from uList in u.DefaultIfEmpty() //左连接 等效于left join
                            select new
                            {
                                id = userRole.Id,
                                uid = userRole.Uid,
                                nickname = Utils.Htmls(uList.NickName),
                                realname = Utils.Htmls(uList.RealName),
                                portrait = ConfigSetting.GetUserLogoAbsoluteUrl(uList.Portrait),
                                account = Utils.Htmls(userAccount.Account),
                                phone = userAccount.Phone,
                                lastTime = DateTimeHelper.GetDateTime(userRole.UpdateTime.ToString()).ToString("yyyy-MM-dd HH:mm:ss"),
                                lastUser = from u in userList where u.Uid == userRole.UpdateUid select string.IsNullOrEmpty(u.RealName) ? Utils.Htmls(u.NickName) : Utils.Htmls(u.RealName),
                            };

            if (totalRecords > 0)
            {
                pageListModel.rows = tableJson;
            }
            else
            {
                pageListModel.rows = userRoleList;
            }
            pageListModel.total = totalRecords;


            return Json(pageListModel);
        }
        #endregion

        #region 获取菜单功能列表
        /// <summary>
        /// 获取菜单功能列表
        /// </summary>
        /// <param name="id">角色id</param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult GetRoleFunctionList(int id)
        {
            MS_Base_RoleLogic roleLogic = MS_Base_RoleLogic.GetInstance();
            MS_Base_FunctionLogic functionLogic = MS_Base_FunctionLogic.GetInstance();
            MS_Base_RoleFunctionLogic roleFunctionLogic = MS_Base_RoleFunctionLogic.GetInstance();

            MS_Base_Role role = roleLogic.GetItemByQuery(x => x.Id == id && x.Status >= (int)RoleStatus.Normal);
            JsonResultModel model = new JsonResultModel();
            if (role == null)
            {
                model.code = Code.ERROR;
                model.message = Message.PARAMERROR;
                model.data = new { };
                return Json(model);
            }

            var functionList = functionLogic.GetListByQuery(x => x.Status == (int)Status.Normal, "Pid,SeqId", false);
            var roleFunctionList = roleFunctionLogic.GetListByQuery(x => x.RoleId == id && x.Status == (int)Status.Normal, string.Empty, false);

            var roleFunctionModelList = (from o in functionList
                                         where o.Pid == 0
                                         select new RoleFunctionModel()
                                         {
                                             id = o.Id,
                                             pid = o.Pid,
                                             name = Utils.ToHtml(o.Name),
                                             roleId = o.Id.ToString(),
                                             isChecked = roleFunctionList.Find(x => x.FunctionId == o.Id) != null,
                                             child = new List<RoleFunctionModel>(),
                                             type = o.Type

                                         }).ToList();

            foreach (RoleFunctionModel roleFunctionModel in roleFunctionModelList)
            {

                GetMenuChild(roleFunctionModel, functionList, roleFunctionList, roleFunctionModel.id.ToString());
            }

            model.code = Code.SUCCESS;
            model.message = Message.SUCCESS;
            //列表数据
            model.data = roleFunctionModelList;

            return Json(model);
        }
        /// <summary>
        /// 递归函数，获取菜单
        /// </summary>
        /// <param name="menu"></param>
        /// <param name="list"></param>
        private void GetMenuChild(RoleFunctionModel menu, List<MS_Base_Function> list, List<MS_Base_RoleFunction> roleFunctionList, string roleId)
        {
            List<RoleFunctionModel> child = (from o in list
                                             where o.Pid == menu.id
                                             select new RoleFunctionModel()
                                             {
                                                 id = o.Id,
                                                 pid = o.Pid,
                                                 name = Utils.ToHtml(o.Name),
                                                 isChecked = roleFunctionList.Find(x => x.FunctionId == o.Id) != null,
                                                 child = new List<RoleFunctionModel>(),
                                                 type = o.Type,

                                             }).ToList();
            if (child.Count == 0)
            {
                return;
            }
            foreach (RoleFunctionModel c in child)
            {

                c.roleId = roleId + "-" + c.id; ;
                menu.child.Add(c);
                GetMenuChild(c, list, roleFunctionList, roleId + "-" + c.id);
            }
        }

        #endregion

        #region 获取列表数据
        /// <summary>
        /// 获取列表数据
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult GetList(string name = "")
        {
            MS_Base_RoleLogic roleLogic = MS_Base_RoleLogic.GetInstance();
            MS_Base_UserRoleLogic userRoleLogic = MS_Base_UserRoleLogic.GetInstance();
            MS_UserCenter_UserAttrLogic userAttrLogic = MS_UserCenter_UserAttrLogic.GetInstance();

            Expression<Func<MS_Base_Role, bool>> expression = PredicateBuilder.True<MS_Base_Role>();
            expression = expression.And(x => x.Status >= (int)Status.Normal);
            if (!string.IsNullOrEmpty(name))
            {
                expression = expression.And(x => x.Name.Contains(name));
            }

            JsonResultModel model = new JsonResultModel();
            List<MS_Base_Role> list = roleLogic.GetListByQuery(expression, "SeqId", false);
            long[] uidArr = list.Select(x => x.UpdateUid == 0 ? x.CreateUid : x.UpdateUid).ToArray();
            int[] roleIdArr = list.Select(x => x.Id).ToArray();
            List<MS_UserCenter_UserAttr> userList = userAttrLogic.GetListByQuery((x => uidArr.Contains(x.Uid)), string.Empty, false);
            List<MS_Base_UserRole> userRoleList = userRoleLogic.GetListByQuery(x => roleIdArr.Contains(x.Id) && x.Status == (int)Status.Normal, string.Empty, false);

            //列表数据
            var tableJsonList = from o in list
                                select new
                                {
                                    id = o.Id,
                                    name = Utils.ToHtml(o.Name),
                                    userCount = userRoleList.Count(x => x.RoleId == o.Id),
                                    status = o.Status,
                                    lastTime = DateTimeHelper.GetDateTime(o.UpdateTime.ToString()).ToString("yyyy-MM-dd HH:mm:ss"),
                                    lastUser = from u in userList where u.Uid == o.UpdateUid select string.IsNullOrEmpty(u.RealName) ? Utils.Htmls(u.NickName) : Utils.Htmls(u.RealName),
                                    isAllowUp = o.SeqId != list.First().SeqId,
                                    isAllowDown = o.SeqId != list.Last().SeqId,
                                };
            model.code = Code.SUCCESS;
            model.message = Message.SUCCESS;
            //列表数据
            model.data = tableJsonList;
            return Json(model);
        }
        #endregion

        #region 获取用户列表
        /// <summary>
        /// 获取用户列表
        /// </summary>
        /// <param name="param"></param>
        /// <param name="roleId"></param>
        /// <param name="searchType">0：uid查询，1用户名查询，2手机号查询，3邮箱查询，4昵称查询，5姓名查询</param>
        /// <param name="searchText"></param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult GetUserList(BootstrapTablePageParamModel param, int roleId, int searchType, string searchText)
        {
            MS_Base_UserRoleLogic userRoleLogic = MS_Base_UserRoleLogic.GetInstance();
            MS_UserCenter_UserAccountLogic userAccountLogic = MS_UserCenter_UserAccountLogic.GetInstance();
            MS_UserCenter_UserAttrLogic userAttrLogic = MS_UserCenter_UserAttrLogic.GetInstance();
            PageListModel pageListModel = new PageListModel();
            int totalRecords = 0;
            List<MS_Base_UserRole> userRoleList = userRoleLogic.GetListByQuery(x => x.RoleId == roleId && x.Status == (int)Status.Normal, null, false);
            List<MS_UserCenter_UserAttr> userAttrList = new List<MS_UserCenter_UserAttr>();

            List<long> uidInUserRoleList = new List<long>();

            if (userRoleList.Count > 0)
            {
                uidInUserRoleList = (from o in userRoleList select o.Uid).ToList();
            }

            Expression<Func<MS_UserCenter_UserAccount, bool>> expression = PredicateBuilder.True<MS_UserCenter_UserAccount>();
            expression = expression.And(x => x.Status >= (int)Status.Normal);
            if (uidInUserRoleList.Count > 0)
            {
                expression = expression.And(x => !uidInUserRoleList.Contains(x.Uid));
            }
            if (!string.IsNullOrEmpty(searchText))
            {
                switch (searchType)
                {
                    //0：uid查询，1用户名查询，2手机号查询，3昵称查询，4姓名查询
                    case 0:
                        //uid
                        long tmp = 0;
                        long.TryParse(searchText, out tmp);
                        expression = expression.And(x => x.Uid == tmp);
                        break;
                    case 1:
                        //用户名
                        expression = expression.And(x => x.Account.Contains(searchText));
                        break;
                    case 2:
                        //手机号
                        expression = expression.And(x => x.Phone.Contains(searchText));
                        break;
                    case 3:
                        //邮箱
                        expression = expression.And(x => x.Email.Contains(searchText));
                        break;
                    case 4:
                        //昵称
                        userAttrList = userAttrLogic.GetListByQuery(x => x.NickName.Contains(searchText) && x.Status == (int)Status.Normal, null, false);
                        if (userAttrList.Count > 0)
                        {
                            List<long> uids = (from o in userAttrList select o.Uid).ToList();
                            expression = expression.And(x => uids.Contains(x.Uid));
                        }
                        else
                        {
                            expression = expression.And(x => x.Uid == -1);
                        }

                        break;
                    case 5:
                        //姓名
                        userAttrList = userAttrLogic.GetListByQuery(x => x.RealName.Contains(searchText) && x.Status == (int)Status.Normal, null, false);
                        if (userAttrList.Count > 0)
                        {
                            List<long> uids = (from o in userAttrList select o.Uid).ToList();
                            expression = expression.And(x => uids.Contains(x.Uid));
                        }
                        else
                        {
                            expression = expression.And(x => x.Uid == -1);
                        }
                        break;
                }
            }

            List<MS_UserCenter_UserAccount> userAccountList = userAccountLogic.GetPagedList(param.offset, param.limit, expression, param.sort, param.sortOrder == "desc", out totalRecords);

            if (userAttrList.Count == 0)
            {
                List<long> uids = (from o in userAccountList select o.Uid).ToList();
                userAttrList = userAttrLogic.GetListByQuery(x => uids.Contains(x.Uid), null, false);
            }
            var tableJson = from userAccount in userAccountList
                            join userAttr in userAttrList.DefaultIfEmpty() on userAccount.Uid equals userAttr.Uid
                            select new
                            {
                                uid = userAccount.Uid,
                                account = Utils.Htmls(userAccount.Account),
                                phone = Utils.Htmls(userAccount.Phone),
                                nickname = Utils.Htmls(userAttr.NickName),
                                realname = Utils.Htmls(userAttr.RealName),
                                gender = EnumHelper.GetEnumDescription((Gender)userAttr.Gender)
                            };
            if (totalRecords > 0)
            {
                pageListModel.rows = tableJson;

            }
            else
            {
                pageListModel.rows = userAccountList;
            }
            pageListModel.total = totalRecords;
            return Json(pageListModel);
        }
        #endregion 

        #region 保存角色
        /// <summary>
        /// 保存角色
        /// </summary>
        /// <param name="id"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult Save(int id, string name)
        {
            JsonResultModel model = new JsonResultModel();
            MS_Base_RoleLogic roleLogic = MS_Base_RoleLogic.GetInstance();
            long loginUid = SecurityIdentity.GetLoginUid(Platform.BMS);
            int res = roleLogic.Save(id, name, loginUid);

            model.code = Code.SUCCESS;
            model.message = Message.SUCCESS;
            model.data = res;
            return Json(model);
        }
        #endregion

        #region 保存角色权限
        /// <summary>
        /// 保存角色权限
        /// </summary>
        /// <param name="roleId"></param>
        /// <param name="functionIdArr"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult SaveRoleFunction(int roleId, List<int> functionIdArr)
        {
            if (functionIdArr == null)
            {
                functionIdArr = new List<int>();
            }
            JsonResultModel model = new JsonResultModel();
            MS_Base_RoleFunctionLogic roleFunctionLogic = MS_Base_RoleFunctionLogic.GetInstance();
            MS_Base_RoleLogic roleLogic = MS_Base_RoleLogic.GetInstance();
            long loginUid = SecurityIdentity.GetLoginUid(Platform.BMS);
            if (!roleLogic.IsExists(x => x.Id == roleId))
            {
                model.code = Code.ERROR;
                model.message = Message.PARAMERROR;
                model.data = Message.PARAMERROR;
                return Json(model);
            }

            roleFunctionLogic.SaveRoleFunction(roleId, functionIdArr, loginUid);


            model.code = Code.SUCCESS;
            model.message = Message.SUCCESS;
            model.data = new { };
            return Json(model);

        }
        #endregion

        #region 添加用户角色
        /// <summary>
        /// 添加用户角色
        /// </summary>
        /// <param name="roleId"></param>
        /// <param name="uids"></param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult AddUserRole(int roleId, List<long> uids)
        {

            JsonResultModel model = new JsonResultModel();
            MS_Base_RoleLogic roleLogic = MS_Base_RoleLogic.GetInstance();
            MS_Base_UserRoleLogic userRoleLogic = MS_Base_UserRoleLogic.GetInstance();


            long loginUid = SecurityIdentity.GetLoginUid(Platform.BMS);
            if (!roleLogic.IsExists(x => x.Id == roleId) || uids == null)
            {
                model.code = Code.ERROR;
                model.message = Message.PARAMERROR;
                model.data = "请至少选择一个用户。";
                return Json(model);
            }

            userRoleLogic.AddRange(roleId, uids, loginUid);
            model.code = Code.SUCCESS;
            model.message = Message.SUCCESS;
            model.data = new { };
            return Json(model);
        }
        #endregion

        #region 切换状态
        /// <summary>
        /// 切换角色状态
        /// </summary>
        /// <param name="id"></param>
        /// <param name="status"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult UpdateStatus(int id, int status)
        {
            JsonResultModel model = new JsonResultModel();
            MS_Base_RoleLogic roleLogic = MS_Base_RoleLogic.GetInstance();
            long loginUid = SecurityIdentity.GetLoginUid(Platform.BMS);
            MS_Base_Role role = roleLogic.GetById(id);
            if (status != (int)RoleStatus.Normal && status != (int)RoleStatus.Stop)
            {
                model.code = Code.ERROR;
                model.message = Message.PARAMERROR;
                model.data = string.Empty;
                return Json(model);
            }

            if (role == null)
            {
                model.code = Code.ERROR;
                model.message = Message.ERROR;
                model.data = "未找到对应id的角色。";
                return Json(model);
            }
            role.Status = status;
            role.UpdateTime = DateTimeHelper.GetTime(DateTime.Now);
            role.UpdateUid = loginUid;
            roleLogic.Save(role);

            model.code = Code.SUCCESS;
            model.message = Message.SUCCESS;
            model.data = string.Empty;
            return Json(model);
        }
        #endregion

        #region 删除
        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult Delete(int id)
        {
            MS_Base_RoleLogic roleLogic = MS_Base_RoleLogic.GetInstance();
            MS_Base_UserRoleLogic userRoleLogic = MS_Base_UserRoleLogic.GetInstance();
            MS_Base_RoleFunctionLogic roleFunctionLogic = MS_Base_RoleFunctionLogic.GetInstance();

            JsonResultModel model = new JsonResultModel();
            if (id <= 0)
            {
                model.code = Code.ERROR;
                model.message = Message.PARAMERROR;
                model.data = new { };
                return Json(model);
            }

            /**
            * id允许被删除的规则如下：
            * 1、角色下没有用户
            * 2、角色没有设置权限
            */
            if (userRoleLogic.IsExists(x => x.RoleId == id && x.Status == (int)Status.Normal))
            {
                model.code = Code.ERROR;
                model.message = Message.ERROR;
                model.data = "该角色已关联用户，请先取消用户的关联。";
                return Json(model);
            }
            if (roleFunctionLogic.IsExists(x => x.RoleId == id && x.Status == (int)Status.Normal))
            {
                model.code = Code.ERROR;
                model.message = Message.ERROR;
                model.data = "该角色已设置权限，请先取消设置的权限。";
                return Json(model);
            }
            long uid = SecurityIdentity.GetLoginUid(Platform.BMS);
            MS_Base_Role role = roleLogic.GetById(id);
            if (role == null)
            {
                model.code = Code.ERROR;
                model.message = Message.ERROR;
                model.data = "未找到对应id的角色。";
                return Json(model);
            }
            role.Status = (int)Status.Delete;
            role.UpdateTime = DateTimeHelper.GetTime(DateTime.Now);
            role.UpdateUid = uid;
            roleLogic.Save(role);

            model.code = Code.SUCCESS;
            model.message = Message.SUCCESS;
            model.data = new { };
            return Json(model);
        }
        #endregion

        #region 删除用户角色
        /// <summary>
        /// 删除用户角色
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult DeleteUserRole(List<int> ids, int roleId)
        {
            JsonResultModel model = new JsonResultModel();
            MS_Base_UserRoleLogic userRoleLogic = MS_Base_UserRoleLogic.GetInstance();
            MS_Base_RoleLogic roleLogic = MS_Base_RoleLogic.GetInstance();
            MS_Base_Role role = roleLogic.GetById(roleId);
            if (role == null)
            {
                model.code = Code.ERROR;
                model.message = Message.ERROR;
                model.data = "未找到对应id的角色。";
                return Json(model);
            }
            if (ids == null)
            {
                model.code = Code.ERROR;
                model.message = Message.PARAMERROR;
                model.data = "请选择要删除的数据";
                return Json(model);
            }

            userRoleLogic.Remove(x => ids.Contains(x.Id));
            long uid = SecurityIdentity.GetLoginUid(Platform.BMS);
            role.UpdateTime = DateTimeHelper.GetTime(DateTime.Now);
            role.UpdateUid = uid;
            roleLogic.Save(role);

            model.code = Code.SUCCESS;
            model.message = Message.SUCCESS;
            model.data = new { };
            return Json(model);
        }
        #endregion

        #region 移动排序
        /// <summary>
        /// 移动排序
        /// </summary>
        /// <param name="id"></param>
        /// <param name="way">移动的方向 1 向上 2向下</param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult Move(int id, int way)
        {
            MS_Base_RoleLogic roleLogic = MS_Base_RoleLogic.GetInstance();
            JsonResultModel model = new JsonResultModel();
            if (id <= 0)
            {
                model.code = Code.ERROR;
                model.message = Message.PARAMERROR;
                model.data = "";
                return Json(model);
            }
            long loginUid = SecurityIdentity.GetLoginUid(Platform.BMS);
            bool b = roleLogic.Move(id, (MoveWay)way, loginUid);
            if (b)
            {
                model.code = Code.SUCCESS;
                model.message = Message.SUCCESS;
                model.data = new { };
            }
            else
            {
                model.code = Code.ERROR;
                model.message = Message.ERROR;
                switch (way)
                {
                    case (int)MoveWay.Up:
                        model.data = "已经到最顶端了";
                        break;
                    case (int)MoveWay.Down:
                        model.data = "已经到最底部了";
                        break;
                    default:
                        model.data = "";
                        break;
                }

            }
            return Json(model);
        }
        #endregion
    }
}